package com.dldata.devtools30.utils.security;

import com.dldata.devtools30.utils.ByteArrayHexStringUtil;
import com.dldata.devtools30.utils.MD5Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Createdby 呵呵 on 2018-03-27.
 */
public class AesUtil {
    private static Log loger = LogFactory.getLog(AesUtil.class);

    /**
     * 加密key
     */
    private  IvParameterSpec dps = new IvParameterSpec("1234567812345678".getBytes());
    private  SecretKeySpec secretKey = new SecretKeySpec("1234567812345678".getBytes(), "AES");

    public AesUtil(){


    }

    public static AesUtil getInstance(String password,String ivparameterspec){
        AesUtil aesUtil=new AesUtil();
        aesUtil.secretKey = new SecretKeySpec(password.getBytes(), "AES");
        aesUtil.dps = new IvParameterSpec(ivparameterspec.getBytes());
        return aesUtil;
    }

    /**
     *
     * decode:Ars加密
     *
     * @param  @param str
     * @param  @return
     * @param  @throws Exception
     * @return byte[]
     * @throws
     * @since  CodingExample　Ver 1.1
     */
    public byte[] encode(byte[] str){
        try{
            Cipher cp = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cp.init(Cipher.ENCRYPT_MODE, secretKey,dps);
            return cp.doFinal(str);
        }catch (Exception e) {
            loger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     *
     * encode:Ars解密
     *
     * @param  @param bye
     * @param  @return
     * @param  @throws Exception
     * @return String
     * @throws
     * @since  CodingExample　Ver 1.1
     */
    public byte[] decode(byte[] bye){
        try{
            Cipher cpjm = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cpjm.init(Cipher.DECRYPT_MODE, secretKey,dps);
            return cpjm.doFinal(bye);
        }catch (Exception e) {
            loger.error(e.getMessage(), e);
        }
        return null; //重新显示明文
    }

    /**
     *
     * decode:Ars加密
     *
     * @param  @param str
     * @param  @return
     * @param  @throws Exception
     * @return byte[]
     * @throws
     * @since  CodingExample　Ver 1.1
     */
    public void encode(InputStream fin, OutputStream fout){
        try{
            Cipher cp = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cp.init(Cipher.ENCRYPT_MODE, secretKey,dps);
            CipherInputStream cipherInputStream = new CipherInputStream(fin, cp);
            byte[] input = new byte[64];
            int len = 0;
            while ((len = cipherInputStream.read(input)) != -1) {
                fout.write(input, 0, len);
            }
            fout.flush();
        }catch (Exception e) {
            loger.error(e.getMessage(), e);
        }
        return;
    }

    /**
     *
     * encode:Ars解密
     *
     * @param  @param bye
     * @param  @return
     * @param  @throws Exception
     * @return String
     * @throws
     * @since  CodingExample　Ver 1.1
     */
    public void decode(InputStream fin, OutputStream fout){
//        try{
//            Cipher cpjm = Cipher.getInstance("AES/CBC/PKCS5Padding");
//            cpjm.init(Cipher.DECRYPT_MODE, secretKey,dps);
//            CipherOutputStream cout = new CipherOutputStream(fout, cpjm);
//            byte[] input = new byte[64];
//            int len = 0;
//            while ((len = fin.read(input)) != -1) {
//                cout.write(input, 0, len);
//            }
//            cout.flush();
//        }catch (Exception e) {
//            loger.error(e.getMessage(), e);
//        }

        try{
            Cipher cpjm = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cpjm.init(Cipher.DECRYPT_MODE, secretKey,dps);
            CipherInputStream cipherInputStream = new CipherInputStream(fin, cpjm);
            byte[] input = new byte[64];
            int len = 0;
            while ((len = cipherInputStream.read(input)) != -1) {
                fout.write(input, 0, len);
            }
            fout.flush();
        }catch (Exception e) {
            loger.error(e.getMessage(), e);
        }
        return;
    }

    public static void main(String[] args) throws Exception {
//        String s = "12345678901234567890123456789012345678901234567890123456789012345678901234567890";
        String s = "12345678901234567890";

        AesUtil aesUtil = new AesUtil();
        aesUtil=AesUtil.getInstance(MD5Util.MD5Encoder("12345678901234567890").substring(0,16),MD5Util.MD5Encoder("12345678901234567890").substring(0,16));
        String encode = ByteArrayHexStringUtil.bytesToHexString(aesUtil.encode(s.getBytes("UTF-8")));
        System.out.println(encode);
        System.out.println(new String(aesUtil.decode(ByteArrayHexStringUtil.hexStringToBytes(encode)),"UTF-8"));

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//        FileOutputStream outputStream=new FileOutputStream("miwen");
        aesUtil.encode(new ByteArrayInputStream(s.getBytes()), byteArrayOutputStream);
//        CypherStreamUtil.encryptFile(new ByteArrayInputStream(s.getBytes()),outputStream,"dldata123", "dldata12".getBytes());
//        outputStream.flush();
//        outputStream.close();
        System.out.println(ByteArrayHexStringUtil.bytesToHexString(byteArrayOutputStream.toByteArray()));
        ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream();
//        outputStream=new FileOutputStream("minwen");
        aesUtil.decode(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()), byteArrayOutputStream2);
        System.out.println(ByteArrayHexStringUtil.bytesToHexString(byteArrayOutputStream2.toByteArray()));
        System.out.println((new String(byteArrayOutputStream2.toByteArray())));
    }

}
